package handler

import (
	"encoding/json"
	"fmt"
	"gin_maker_chat/dao"
	"gin_maker_chat/model"
	"gin_maker_chat/server/utils"
	"net"
)

type UserHandler struct {
	Conn net.Conn
	//增加一个标识，该连接属于哪个用户
	UserName string
}

// 通知所有人在线
// userName 要通知其他在线用户，我上线
func (this *UserHandler) NotifyOtherOnlineUser(userName string) {
	//遍历在线用户，发送在线通知消息
	for name, uh := range userMgr.OnlineUsers {
		if name == userName {
			continue
		}
		//开始通知其他人
		uh.NotifyMeToOnlineUser(userName)
	}
}

// 开始通知其他人
func (this *UserHandler) NotifyMeToOnlineUser(userName string) {
	//发送消息
	var msg model.Message
	msg.Type = model.NotifyUserStatusMsgType

	var notifyUserStatusMsg model.NotifyUserStatusMsg
	notifyUserStatusMsg.UserName = userName
	notifyUserStatusMsg.Status = model.UserOnline

	data, err := json.Marshal(notifyUserStatusMsg)
	if err != nil {
		fmt.Println("notifyUserStatusMsg json.marshal err:", err)
		return

	}

	msg.Data = string(data)
	data, err = json.Marshal(msg)
	if err != nil {
		fmt.Println("notifyUser Msg json.marshal err:", err)
		return
	}
	transfer := &utils.Transfer{
		Conn: this.Conn,
	}
	err = transfer.WriteMsgByNetCon(data)
	if err != nil {
		fmt.Println("notifyUserStatusMsg transfer.WriteMsgByNetCon,err=", err)
	}
	return
}

func (this *UserHandler) HandlerLoginMsg(msg *model.Message) (err error) {
	var loginMsg model.LoginMsg
	err = json.Unmarshal([]byte(msg.Data), &loginMsg)
	if err != nil {
		fmt.Println("json.Unmarshal err:", err)
		return
	}
	var resMsg model.Message
	resMsg.Type = model.LoginResMsgType

	var loginResMsg model.LoginResMsg
	user, err := dao.MyUserDao.UserLogin(loginMsg.UserName, loginMsg.PassWord)
	if err != nil {
		if err == model.ERROR_USER_NOT_EXISTS {
			loginResMsg.Code = 500
			loginResMsg.Error = err.Error()
		} else if err == model.ERROR_USER_PWD {
			loginResMsg.Code = 403
			loginResMsg.Error = err.Error()
		} else {
			loginResMsg.Code = 505
			loginResMsg.Error = "服务器内部错误"
		}
	} else {
		loginResMsg.Code = 200
		fmt.Println("user login success.该用户user=", user)
		//初始化在线用户列表
		this.UserName = loginMsg.UserName
		//新登录的用户添加到在线列表中
		userMgr.AddOnlineUser(this)
		//通知其他用户，我上线了
		this.NotifyOtherOnlineUser(loginMsg.UserName)
		//将在线用户的CODE返回给当前用户
		for code, _ := range userMgr.OnlineUsers {
			loginResMsg.UserNames = append(loginResMsg.UserNames, code)
		}

	}
	// if loginMsg.UserName == "admin" && loginMsg.PassWord == "123456" {
	// 	loginResMsg.Code = 200
	// } else {
	// 	loginResMsg.Code = 500
	// 	loginResMsg.Error = "用户信息异常，请核实"
	// }

	//将loginResMsg序列化
	data, err := json.Marshal(loginResMsg)
	if err != nil {
		fmt.Println("loginResMsg json.marshal err:", err)
		return
	}
	resMsg.Data = string(data)

	data, err = json.Marshal(resMsg)
	if err != nil {
		fmt.Println("loginResMsg json.marshal err:", err)
		return
	}

	//发送data,封装成WriteMsgByNetCon进行处理
	transfer := utils.Transfer{
		Conn: this.Conn,
	}
	err = transfer.WriteMsgByNetCon(data)
	return
}

func (this *UserHandler) HandlerResisterMsg(msg *model.Message) (err error) {
	var registerMsg model.RegisterMsg
	err = json.Unmarshal([]byte(msg.Data), &registerMsg)
	if err != nil {
		fmt.Println("server registerMsg json.Unmarshal err:", err)
		return
	}

	var resMsg model.Message
	resMsg.Type = model.RegisterResMsgType
	var registerResMsg model.RegisterResMsg
	err = dao.MyUserDao.UserRegister(&registerMsg.User)
	if err != nil {
		if err == model.ERROR_USER_EXISTS {
			registerResMsg.Code = 505
			registerResMsg.Error = model.ERROR_USER_EXISTS.Error()
		} else {
			registerResMsg.Code = 50
			registerResMsg.Error = "服务器端未知错误"
		}
	} else {
		registerResMsg.Code = 200
		fmt.Println("user register success,user=", registerMsg.User)
	}

	//将registerResMsg序列化
	data, err := json.Marshal(registerResMsg)
	if err != nil {
		fmt.Println("registerResMsg序列化 json.marshal err:", err)
		return
	}
	resMsg.Data = string(data)

	data, err = json.Marshal(resMsg)
	if err != nil {
		fmt.Println("将registerResMsg序列化 json.marshal err:", err)
		return
	}

	//发送data,封装成WriteMsgByNetCon进行处理
	transfer := utils.Transfer{
		Conn: this.Conn,
	}
	err = transfer.WriteMsgByNetCon(data)
	return
}
